﻿''' <summary>
''' バージョンキー列属性
''' </summary>
''' <remarks>
''' 楽観的ロックを行うための列
''' 主キーではありません
''' </remarks>
Public Class VersionKeyAttribute
    Inherits ColumnAttribute

#Region "Constructor"
    Public Sub New()
        'Load関数を差し替える
        Me.ReLoadWhereCommandCreater = AddressOf Me.CreateLoadWhereCommand

        'Save関数を差し替える
        Me.DirtyChecker = Function() False
        Me.InsertColumnCommandCreater = AddressOf Me.CreateInsertColumnCommand
        Me.UpdateColumnCommandCreater = AddressOf Me.CreateUpdateColumnCommand
        Me.SaveWhereCommandCreater = AddressOf Me.CreateSaveWhereCommand
    End Sub

    Public Sub New(ByVal ColumnName As String)
        Me.New()
        Me.ColumnName = ColumnName
    End Sub
#End Region

    ''' <summary>
    ''' 上限
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks>上限を超えるとバージョンは 1 に戻ります。</remarks>
    Property UpperLimit As Integer = 9999

    Private Sub CreateLoadWhereCommand(value As Object, sqlBuilder As Action(Of String), paramRegister As Func(Of Object, String))
        Dim pname As String = paramRegister.Invoke(value)
        sqlBuilder.Invoke(String.Format("{0} = {1}", Me.ColumnName, pname))
    End Sub

    Private Sub CreateSaveWhereCommand(instance As Object, archiveValue As Object, sqlBuilder As Action(Of String), paramRegister As Func(Of Object, String))
        Dim pname As String = paramRegister.Invoke(archiveValue)
        sqlBuilder.Invoke(String.Format("{0} = {1}", Me.ColumnName, pname))
    End Sub

    Private Sub CreateInsertColumnCommand(instance As Object, sqlColumnBuilder As System.Action(Of String), sqlValueBuilder As System.Action(Of String), paramRegister As System.Func(Of Object, Type, String))
        '既存の値を強制補正
        Me.SetValue(instance, 1)

        Me.DefaultInsertColumnCreater(instance, sqlColumnBuilder, sqlValueBuilder, paramRegister)
    End Sub

    Private Sub CreateUpdateColumnCommand(instance As Object, archiveValue As Object, sqlBuilder As System.Action(Of String), paramRegister As System.Func(Of Object, Type, String))
        '既存の値を強制補正
        Dim ver As Integer = Int32.Parse(archiveValue)
        ver += 1
        If Me.UpperLimit <= ver Then ver = 1
        Me.SetValue(instance, ver)

        'ダーティチェックを通さず直接更新
        Dim pname As String = paramRegister.Invoke(ver, Me.PropertyInfo.PropertyType)
        sqlBuilder.Invoke(String.Format("{0} = {1}", Me.ColumnName, pname))
    End Sub

End Class
